/*
 * @Description  :
 * @Version      : 0.1
 * @Company      : V-Think Development Team
 * @Author       : KiraVerSace@yeah.net
 * @Date         : 2025-01-03 16:50:54
 */
#include <appModbus.h>

ModbusRTUSlave modbusRTUSlave(MODBUS_SERIAL, MODBUS_DE, MODBUS_RE);

const uint8_t num03HoldingRegister = 120;
uint16_t holdingRegister[num03HoldingRegister];

void modbusSerialConfig(uint8_t slaveAddress);

osThreadId modbusSlaveTaskHandle;
void modbusSlaveTask(void *pvParameters)
{
    UNUSED(pvParameters);
    xLog.info("modbusSlaveTask...[%d]\r\n", uxTaskGetStackHighWaterMark(NULL));

    holdingRegister[MB_MV_CH1] = 0;
    holdingRegister[MB_MV_CH2] = 0;
    holdingRegister[MB_RELAY_OUTPUT] = 0;

    BaseType_t result = pdFALSE;
    XSensorDataT xSensorData;

    // Modbus 第一次运行加载默认值
    static bool firstRun = true;

    // 参数保存延迟处理标志
    static bool     paramChanged    = false;
    static uint32_t paramChangeTime = 0;
    static bool     paramSaved      = false;

    modbusSerialConfig(xParameter.modbusAddress);

    modbusRTUSlave.configureHoldingRegisters(holdingRegister, num03HoldingRegister);

    holdingRegister[MB_MV_CH1] = xParameter.defaultCH1Output;
    holdingRegister[MB_MV_CH2] = xParameter.defaultCH2Output;
    holdingRegister[MB_RELAY_OUTPUT] = xParameter.defaultRelayOutput;

    while (1)
    {
        holdingRegister[MB_ADDRESS]   = xParameter.modbusAddress;
        holdingRegister[MB_BAUD_RATE] = xParameter.baudRate;
        holdingRegister[MB_PARITY]    = xParameter.parity;
        holdingRegister[MB_STOP_BIT]  = xParameter.stopBit;
        holdingRegister[MB_DA_DEFAULT_CH1]   = xParameter.defaultCH1Output;
        holdingRegister[MB_DA_DEFAULT_CH2]   = xParameter.defaultCH2Output;
        holdingRegister[MB_DA_DEFAULT_RELAY] = xParameter.defaultRelayOutput;

        holdingRegister[MB_DA_CALIBRATION_A0]  = xParameter.dacCalibrationA0;
        holdingRegister[MB_DA_CALIBRATION_A1]  = xParameter.dacCalibrationA1;
        holdingRegister[MB_DA_CALIBRATION_A2]  = xParameter.dacCalibrationA2;
        holdingRegister[MB_DA_CALIBRATION_A3]  = xParameter.dacCalibrationA3;
        holdingRegister[MB_DA_CALIBRATION_A4]  = xParameter.dacCalibrationA4;
        holdingRegister[MB_DA_CALIBRATION_A5]  = xParameter.dacCalibrationA5;
        holdingRegister[MB_DA_CALIBRATION_A6]  = xParameter.dacCalibrationA6;
        holdingRegister[MB_DA_CALIBRATION_A7]  = xParameter.dacCalibrationA7;
        holdingRegister[MB_DA_CALIBRATION_A8]  = xParameter.dacCalibrationA8;
        holdingRegister[MB_DA_CALIBRATION_A9]  = xParameter.dacCalibrationA9;
        holdingRegister[MB_DA_CALIBRATION_A10] = xParameter.dacCalibrationA10;

        holdingRegister[MB_DA_CALIBRATION_B0]  = xParameter.dacCalibrationB0;
        holdingRegister[MB_DA_CALIBRATION_B1]  = xParameter.dacCalibrationB1;
        holdingRegister[MB_DA_CALIBRATION_B2]  = xParameter.dacCalibrationB2;
        holdingRegister[MB_DA_CALIBRATION_B3]  = xParameter.dacCalibrationB3;
        holdingRegister[MB_DA_CALIBRATION_B4]  = xParameter.dacCalibrationB4;
        holdingRegister[MB_DA_CALIBRATION_B5]  = xParameter.dacCalibrationB5;
        holdingRegister[MB_DA_CALIBRATION_B6]  = xParameter.dacCalibrationB6;
        holdingRegister[MB_DA_CALIBRATION_B7]  = xParameter.dacCalibrationB7;
        holdingRegister[MB_DA_CALIBRATION_B8]  = xParameter.dacCalibrationB8;
        holdingRegister[MB_DA_CALIBRATION_B9]  = xParameter.dacCalibrationB9;
        holdingRegister[MB_DA_CALIBRATION_B10] = xParameter.dacCalibrationB10;

        xSensorData.mvCH1             = holdingRegister[MB_MV_CH1];
        xSensorData.mvCH2             = holdingRegister[MB_MV_CH2];
        xSensorData.relayOutput       = holdingRegister[MB_RELAY_OUTPUT];

        modbusRTUSlave.poll();

        if ((firstRun == true)
            || (xSensorData.mvCH1 != holdingRegister[MB_MV_CH1]) || (xSensorData.mvCH2 != holdingRegister[MB_MV_CH2])
            || (xSensorData.relayOutput != holdingRegister[MB_RELAY_OUTPUT])
            || (paramSaved == true))
        {
            firstRun   = false;
            paramSaved = false;

            xSensorData.mvCH1             = holdingRegister[MB_MV_CH1];
            xSensorData.mvCH2             = holdingRegister[MB_MV_CH2];
            xSensorData.relayOutput       = holdingRegister[MB_RELAY_OUTPUT];

            xLog.trace("CH1=[%d]mv CH2=[%d]mv Relay=[%d]\r\n",
                            xSensorData.mvCH1, xSensorData.mvCH2, xSensorData.relayOutput);

            if (xQueueSend( xSensorDataQueue, (void *) &xSensorData, (TickType_t) 10) != pdPASS )
            {
                xLog.warning("xSensorDataQueue Send error...\r\n");
            }
            else
            {
                xLog.trace("xSensorDataQueue Send success...\r\n");
            }
        }

        if ((xParameter.modbusAddress != holdingRegister[MB_ADDRESS])
            || (xParameter.baudRate   != holdingRegister[MB_BAUD_RATE])
            || (xParameter.parity     != holdingRegister[MB_PARITY])
            || (xParameter.stopBit    != holdingRegister[MB_STOP_BIT])
            || (xParameter.defaultCH1Output != holdingRegister[MB_DA_DEFAULT_CH1])
            || (xParameter.defaultCH2Output != holdingRegister[MB_DA_DEFAULT_CH2])
            || (xParameter.defaultRelayOutput != holdingRegister[MB_DA_DEFAULT_RELAY])
            || (xParameter.dacCalibrationA0  != holdingRegister[MB_DA_CALIBRATION_A0])
            || (xParameter.dacCalibrationA1  != holdingRegister[MB_DA_CALIBRATION_A1])
            || (xParameter.dacCalibrationA2  != holdingRegister[MB_DA_CALIBRATION_A2])
            || (xParameter.dacCalibrationA3  != holdingRegister[MB_DA_CALIBRATION_A3])
            || (xParameter.dacCalibrationA4  != holdingRegister[MB_DA_CALIBRATION_A4])
            || (xParameter.dacCalibrationA5  != holdingRegister[MB_DA_CALIBRATION_A5])
            || (xParameter.dacCalibrationA6  != holdingRegister[MB_DA_CALIBRATION_A6])
            || (xParameter.dacCalibrationA7  != holdingRegister[MB_DA_CALIBRATION_A7])
            || (xParameter.dacCalibrationA8  != holdingRegister[MB_DA_CALIBRATION_A8])
            || (xParameter.dacCalibrationA9  != holdingRegister[MB_DA_CALIBRATION_A9])
            || (xParameter.dacCalibrationA10 != holdingRegister[MB_DA_CALIBRATION_A10])
            || (xParameter.dacCalibrationB0  != holdingRegister[MB_DA_CALIBRATION_B0])
            || (xParameter.dacCalibrationB1  != holdingRegister[MB_DA_CALIBRATION_B1])
            || (xParameter.dacCalibrationB2  != holdingRegister[MB_DA_CALIBRATION_B2])
            || (xParameter.dacCalibrationB3  != holdingRegister[MB_DA_CALIBRATION_B3])
            || (xParameter.dacCalibrationB4  != holdingRegister[MB_DA_CALIBRATION_B4])
            || (xParameter.dacCalibrationB5  != holdingRegister[MB_DA_CALIBRATION_B5])
            || (xParameter.dacCalibrationB6  != holdingRegister[MB_DA_CALIBRATION_B6])
            || (xParameter.dacCalibrationB7  != holdingRegister[MB_DA_CALIBRATION_B7])
            || (xParameter.dacCalibrationB8  != holdingRegister[MB_DA_CALIBRATION_B8])
            || (xParameter.dacCalibrationB9  != holdingRegister[MB_DA_CALIBRATION_B9])
            || (xParameter.dacCalibrationB10 != holdingRegister[MB_DA_CALIBRATION_B10]))
        {
            // 更新Modbus配置参数
            xParameter.modbusAddress  = holdingRegister[MB_ADDRESS];
            xParameter.baudRate       = holdingRegister[MB_BAUD_RATE];
            xParameter.parity         = holdingRegister[MB_PARITY];
            xParameter.stopBit        = holdingRegister[MB_STOP_BIT];
            xParameter.defaultCH1Output   = holdingRegister[MB_DA_DEFAULT_CH1];
            xParameter.defaultCH2Output   = holdingRegister[MB_DA_DEFAULT_CH2];
            xParameter.defaultRelayOutput = holdingRegister[MB_DA_DEFAULT_RELAY];

            // 更新DAC校准参数A (CH1)
            xParameter.dacCalibrationA0  = holdingRegister[MB_DA_CALIBRATION_A0];
            xParameter.dacCalibrationA1  = holdingRegister[MB_DA_CALIBRATION_A1];
            xParameter.dacCalibrationA2  = holdingRegister[MB_DA_CALIBRATION_A2];
            xParameter.dacCalibrationA3  = holdingRegister[MB_DA_CALIBRATION_A3];
            xParameter.dacCalibrationA4  = holdingRegister[MB_DA_CALIBRATION_A4];
            xParameter.dacCalibrationA5  = holdingRegister[MB_DA_CALIBRATION_A5];
            xParameter.dacCalibrationA6  = holdingRegister[MB_DA_CALIBRATION_A6];
            xParameter.dacCalibrationA7  = holdingRegister[MB_DA_CALIBRATION_A7];
            xParameter.dacCalibrationA8  = holdingRegister[MB_DA_CALIBRATION_A8];
            xParameter.dacCalibrationA9  = holdingRegister[MB_DA_CALIBRATION_A9];
            xParameter.dacCalibrationA10 = holdingRegister[MB_DA_CALIBRATION_A10];

            // 更新DAC校准参数B (CH2)
            xParameter.dacCalibrationB0  = holdingRegister[MB_DA_CALIBRATION_B0];
            xParameter.dacCalibrationB1  = holdingRegister[MB_DA_CALIBRATION_B1];
            xParameter.dacCalibrationB2  = holdingRegister[MB_DA_CALIBRATION_B2];
            xParameter.dacCalibrationB3  = holdingRegister[MB_DA_CALIBRATION_B3];
            xParameter.dacCalibrationB4  = holdingRegister[MB_DA_CALIBRATION_B4];
            xParameter.dacCalibrationB5  = holdingRegister[MB_DA_CALIBRATION_B5];
            xParameter.dacCalibrationB6  = holdingRegister[MB_DA_CALIBRATION_B6];
            xParameter.dacCalibrationB7  = holdingRegister[MB_DA_CALIBRATION_B7];
            xParameter.dacCalibrationB8  = holdingRegister[MB_DA_CALIBRATION_B8];
            xParameter.dacCalibrationB9  = holdingRegister[MB_DA_CALIBRATION_B9];
            xParameter.dacCalibrationB10 = holdingRegister[MB_DA_CALIBRATION_B10];

            // 标记参数需要保存，设置延迟处理
            paramChanged    = true;
            paramChangeTime = millis();
        }

        // 延迟处理参数保存 - 避免频繁EEPROM操作导致死机
        if (paramChanged && (millis() - paramChangeTime) > 1000)
        {
            paramChanged = false;
            paramSaved   = true;

            // 保存到EEPROM
            EEPROM.put(1, xParameter);

            // 更新DAC校准表
            updateDacCalibrationTable();

            printParameterTable();
        }

        watchdogReport(WATCHDOG_SRC_MODBUS);
        vTaskDelay(20);
    }
}

void modbusSerialConfig(uint8_t slaveAddress)
{
    uint8_t serialConfig = SERIAL_8N1;

    if (xParameter.parity == PARITY_NONE)
    {
        if (xParameter.stopBit == STOP_BITS_1)
        {
            serialConfig = SERIAL_8N1;
        }
        else
        {
            serialConfig = SERIAL_8N2;
        }
    }
    else if (xParameter.parity == PARITY_ODD)
    {
        if (xParameter.stopBit == STOP_BITS_1)
        {
            serialConfig = SERIAL_8O1;
        }
        else
        {
            serialConfig = SERIAL_8O2;
        }
    }
    else if (xParameter.parity == PARITY_EVEN)
    {
        if (xParameter.stopBit == STOP_BITS_1)
        {
            serialConfig = SERIAL_8E1;
        }
        else
        {
            serialConfig = SERIAL_8E2;
        }
    }
    else
    {
        xLog.error("Serial config error...\r\n");
    }

    if (xParameter.baudRate == BAUD_RATE_4800)
    {
        MODBUS_SERIAL.begin(4800, serialConfig);
        modbusRTUSlave.begin(slaveAddress, 4800, serialConfig); // 此处并非重复配置,而是为了计算超时时间
    }
    else if (xParameter.baudRate == BAUD_RATE_9600)
    {
        MODBUS_SERIAL.begin(9600, serialConfig);
        modbusRTUSlave.begin(slaveAddress, 9600, serialConfig);
    }
    else if (xParameter.baudRate == BAUD_RATE_19200)
    {
        MODBUS_SERIAL.begin(19200, serialConfig);
        modbusRTUSlave.begin(slaveAddress, 19200, serialConfig);
    }
    else if (xParameter.baudRate == BAUD_RATE_38400)
    {
        MODBUS_SERIAL.begin(38400, serialConfig);
        modbusRTUSlave.begin(slaveAddress, 38400, serialConfig);
    }
    else if (xParameter.baudRate == BAUD_RATE_57600)
    {
        MODBUS_SERIAL.begin(57600, serialConfig);
        modbusRTUSlave.begin(slaveAddress, 57600, serialConfig);
    }
    else if (xParameter.baudRate == BAUD_RATE_115200)
    {
        MODBUS_SERIAL.begin(115200, serialConfig);
        modbusRTUSlave.begin(slaveAddress, 115200, serialConfig);
    }
    else
    {
        xLog.error("Serial baud rate error...\r\n");
    }
}
